package com.xianggu.lock;

import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.LockSupport;

/**
 * @author chengjy
 * @date 2025/3/19
 */
public class XiangGuLock implements Lock{

    private volatile AtomicBoolean isLock = new AtomicBoolean(false);
    // 需要头结点是因为唤醒从头开始唤醒
    private AtomicReference<Node>  head = new AtomicReference<>(new Node(null,null));
    // 需要尾结点是因为排队从后排
    private AtomicReference<Node>  tail = new AtomicReference<>(head.get());

    private Thread currentThread;

    // 是否公平锁
    private boolean isEquity = false;

    // 加锁
    @Override
    public void lock(){
        // 判断是否可以获取锁( 1、公平锁 2、尾结点为空 3、 取锁成功)
        if( (!isEquity || head.get().next == null) && isLock.compareAndSet(false, true)){
            // 非公平锁逻辑
            this.currentThread = Thread.currentThread();
            System.out.println("1、线程" + Thread.currentThread().getName() + "抢到了锁 锁状态：" + (isEquity?"公平锁 ":"非公平锁 ") + "头节点的next线程："+ head.get().next+ "尾节点的next线程："+ tail.get());
            return;
        }

        Node current = new Node(tail.get() , Thread.currentThread());

        // 一直尝试知道将当前节点加入尾结点
        while (true){
            Node currentTail = tail.get();
            if (tail.compareAndSet(currentTail , current)) {
                currentTail.next = current;
                current.pre = currentTail;
                System.out.println("a、线程" + Thread.currentThread().getName() + "加入等待队列");
                break;
            }
        }
        // 判断是否虚假唤醒（只有头结点的下个节点为在自己、且持锁状态修改返回true才可退出阻塞、执行资源方法）
        while (true){
            if(head.get().next == current && isLock.compareAndSet(false , true)){
                // 断掉引用 让自己成为一个空的头结点，并设置持锁线程为自己、这是解锁的必须条件
                current.pre = null;
                head.get().next = null;
                head.set(current);
                this.currentThread = Thread.currentThread();
                System.out.println("b、线程" + Thread.currentThread().getName() + "获得了锁");
                return;
            }
            // 阻塞线程
            LockSupport.park();
        }
    }

    // 释放锁
    @Override
    public void unlock(){
        if (this.currentThread == Thread.currentThread()){
            // 判断是否可以释放锁
            isLock.set(false);
            Node head = this.head.get();
            if (head.next != null) {
                // 存在阻塞线程则唤醒
                LockSupport.unpark(head.next.thread);
//                System.out.println("2、"+Thread.currentThread().getName() + "释放锁 并唤醒下一个阻塞的线程"+ head.next.thread.getName());
            }
        }else {
            throw new RuntimeException("当前线程未持有锁");
        }

    }

    public XiangGuLock(boolean isEquity) {
        this.isEquity = isEquity;
    }

    public XiangGuLock() {
        this.isEquity = false;
    }
}
